﻿using System;
using System.IO;
using System.Linq;
using System.Text;
using System.Web.UI;
using System.Web.UI.HtmlControls;
using System.Web.UI.WebControls;
using CustomerContactSystem.Core.AppServices.Query;
using CustomerContactSystem.Core.Infrastructure.Utility;
using CustomerContactSystem.Core.Model;
using NHibernate;

namespace CustomerContactSystem.WebForms.Enquiries
{
    public partial class Search : BasePage
    {
        private string _optionsHeaderId = "";
        private const int PageSize = 20;
        public int CurrentPage
        {
            get { return Request.QueryString["page"] != null ? int.Parse(Request.QueryString["page"]) : 1; }
        }

        protected void Page_Load(object sender, EventArgs e) {
            if (!IsValidPageRequest(true, true, "")) {
                return;
            }

            if (Request.QueryString["view"] != null) {
                FindEnquiries();
                Response.Clear();
                Response.AddHeader("content-disposition", "attachment;filename=Enquiries.xls");
                Response.Charset = "";
                Response.ContentType = "application/vnd.ms-xls";
                var stringWriter = new StringWriter();
                var htmlWriter = new HtmlTextWriter(stringWriter);
                EnquiriesList.RenderControl(htmlWriter);
                Response.Write(stringWriter.ToString());
                Response.End();
            }
            else {
                GetClassifications();
                GetEnquirySources();
                GetDepartments();
                GetGroups();
                GetUsers();
                GetCategories();
                GetTags();
                SetValuesFromQueryString();
                ExcelLink.NavigateUrl = "~/Enquiries/Search.aspx?" + GetQueryString(true) + "&view=excel";
                CreateNewLink.NavigateUrl = "~/Enquiries/Create.aspx";
                if (Request.QueryString.Count > 0)
                {
                    SearchForm.Attributes.Add("class", "search-form collapsed");
                    FindEnquiries();
                }
                else {
                    PagingList.Visible = false;
                    ExcelLink.Visible = false;
                }
            }
        }

        private void GetClassifications() {
            var enquiryClassifications = EnquiryClassificationRepository.QueryOver().OrderBy(c => c.Classification).Asc.List();
            BindDropDownList(EnquiryClassification, enquiryClassifications, "Classification", "Id", "--Any--", "0");
        }

        private void GetEnquirySources() {
            var enquirySources = EnquirySourceRepository.QueryOver().OrderBy(s => s.SourceName).Asc.List();
            BindDropDownList(EnquirySource, enquirySources, "SourceName", "Id", "--Any--", "0");
        }

        private void GetDepartments() {
            var departments = DepartmentRepository.QueryOver().OrderBy(d => d.DepartmentName).Asc.List();
            BindDropDownList(LoggedByDepartments, departments, "DepartmentName", "Id", "--Any Department--", "0");
            BindDropDownList(ReferredToDepartments, departments, "DepartmentName", "Id", "--Any Department--", "0");
        }

        private void GetGroups() {
            var userGroups = UserGroupRepository.QueryOver().OrderBy(g => g.GroupName).Asc.List();
            BindDropDownList(LoggedByGroups, userGroups, "GroupName", "Id", "--Any Group--", "0");
            BindDropDownList(ReferredToGroups, userGroups, "GroupName", "Id", "--Any Group--", "0");
        }

        private void GetUsers() {
            var users = UserRepository.QueryOver().OrderBy(u => u.DisplayName).Asc.List();
            BindDropDownList(LoggedByUsers, users, "DisplayName", "Id", "--Any User--", "0");
            BindDropDownList(ReferredToUsers, users, "DisplayName", "Id", "--Any User--", "0");
            BindDropDownList(EverReferredToUsers, users, "DisplayName", "Id", "--Any User--", "0");
        }

        private void GetCategories() {
            var categories = EnquiryCategoryRepository.QueryOver().OrderBy(c => c.CategoryName).Asc.List();
            BindDropDownList(Categories, categories, "CategoryName", "Id", "--Any--", "0");
        }

        private void GetTags() {
            var tags = TagRepository.QueryOver().OrderBy(t => t.TagName).Asc.List();
            BindDropDownList(Tags, tags, "TagName", "Id", "--Anything--", "0");
        }

        protected void SearchEnquiriesClick(object sender, EventArgs e) {
            Response.Redirect("~/Enquiries/Search.aspx?" + GetQueryString(true));
        }

        private string GetQueryString(bool includeId) {
            var sb = new StringBuilder();
            if (includeId) {
                sb.Append("id=" + EnquiryId.Text);
            }
            sb.Append("&ty=" + EnquiryTypes.SelectedItem.Value);
            sb.Append("&fysid=" + FixYourStreetId.Text);
            sb.Append("&cl=" + EnquiryClassification.SelectedItem.Value);
            sb.Append("&rf=" + ReceivedFromDate.Text.Replace("/", "-"));
            sb.Append("&rt=" + ReceivedToDate.Text.Replace("/", "-"));
            sb.Append("&df=" + DeadlineFrom.Text.Replace("/", "-"));
            sb.Append("&dt=" + DeadlineTo.Text.Replace("/", "-"));
            sb.Append("&st=" + EnquiryStatus.SelectedItem.Value);
            sb.Append("&so=" + EnquirySource.SelectedItem.Value);
            sb.Append("&ld=" + LoggedByDepartments.SelectedItem.Value);
            sb.Append("&lg=" + LoggedByGroups.SelectedItem.Value);
            sb.Append("&lu=" + LoggedByUsers.SelectedItem.Value);
            sb.Append("&cwd=" + ReferredToDepartments.SelectedItem.Value);
            sb.Append("&cwg=" + ReferredToGroups.SelectedItem.Value);
            sb.Append("&cwu=" + ReferredToUsers.SelectedItem.Value);
            sb.Append("&ert=" + EverReferredToUsers.SelectedItem.Value);
            sb.Append("&ca=" + Categories.SelectedItem.Value);
            sb.Append("&mo=" + MediaOnly.Checked);
            sb.Append("&tw=" + Tags.SelectedItem.Value);
            sb.Append("&ob=" + OrderBy.SelectedItem.Value);
            sb.Append("&obo=" + OrderByOrder.SelectedItem.Value);
            return sb.ToString();
        }

        private void SetValuesFromQueryString() {
            EnquiryId.Text = QueryStringOrEmpty("id");
            SetDropDownListIndexFromQueryStringValue(EnquiryTypes, "ty");
            FixYourStreetId.Text = QueryStringOrEmpty("fysid");
            SetDropDownListIndexFromQueryStringValue(EnquiryClassification, "cl");
            ReceivedFromDate.Text = QueryStringOrEmptyDate("rf");
            ReceivedToDate.Text = QueryStringOrEmptyDate("rt");
            DeadlineFrom.Text = QueryStringOrEmptyDate("df");
            DeadlineTo.Text = QueryStringOrEmptyDate("dt");
            SetDropDownListIndexFromQueryStringValue(EnquiryStatus, "st");
            SetDropDownListIndexFromQueryStringValue(EnquirySource, "so");
            SetDropDownListIndexFromQueryStringValue(LoggedByDepartments, "ld");
            SetDropDownListIndexFromQueryStringValue(LoggedByGroups, "lg");
            SetDropDownListIndexFromQueryStringValue(LoggedByUsers, "lu");
            SetDropDownListIndexFromQueryStringValue(ReferredToDepartments, "cwd");
            SetDropDownListIndexFromQueryStringValue(ReferredToGroups, "cwg");
            SetDropDownListIndexFromQueryStringValue(ReferredToUsers, "cwu");
            SetDropDownListIndexFromQueryStringValue(EverReferredToUsers, "ert");
            SetDropDownListIndexFromQueryStringValue(Categories, "ca");
            MediaOnly.Checked = QueryStringOrFalse("mo");
            SetDropDownListIndexFromQueryStringValue(Tags, "tw");
            SetDropDownListIndexFromQueryStringValue(OrderBy, "ob");
            SetDropDownListIndexFromQueryStringValue(OrderByOrder, "obo");
        }

        private void FindEnquiries() {
            var criteria = BuildCriteria();
            var enquiries = criteria.Result().GetExecutableQueryOver(Global.SessionFactory.GetCurrentSession());
            
            if (Request.QueryString["view"] == null)
            {
                EnquiriesList.DataSource = enquiries.Skip((CurrentPage - 1) * PageSize).Take(PageSize).List();
                var totalRecords =
                    CriteriaTransformer.TransformToRowCount(enquiries.UnderlyingCriteria).UniqueResult<int>();
                SetupPaging(totalRecords);
            }
            else
            {
                EnquiriesList.DataSource = enquiries.List();
            }

            EnquiriesList.DataBind();
        }

        private EnquirySearchQuery BuildCriteria() {
            var criteria = new EnquirySearchQuery
                {
                    EnquiryId = QueryStringOrZero("id"),
                    EnquiryTypeId = QueryStringOrZero("ty"),
                    FixYourStreetId = QueryStringOrZero("fysid"),
                    ClassificationId = QueryStringOrZero("cl"),
                    ReceivedFrom = QueryStringOrMinDate("rf"),
                    ReceivedTo = QueryStringOrMinDate("rt"),
                    DeadlineFrom = QueryStringOrMinDate("df"),
                    DeadlineTo = QueryStringOrMinDate("dt"),
                    EnquiryStatusId = QueryStringOrZero("st"),
                    EnquirySourceId = QueryStringOrZero("so"),
                    LoggedByUserId = QueryStringOrZero("lu"),
                    LoggedByDepartmentId = QueryStringOrZero("ld"),
                    LoggedByGroupId = QueryStringOrZero("lg"),
                    CurrentlyReferredToId = QueryStringOrZero("cwu"),
                    CurrentlyReferredToDepartmentId = QueryStringOrZero("cwd"),
                    CurrentlyReferredToGroupId = QueryStringOrZero("cwg"),
                    EverReferredToId = QueryStringOrZero("ert"),
                    CategoryId = QueryStringOrZero("ca"),
                    MediaOnly = QueryStringOrFalse("mo"),
                    TagId = QueryStringOrZero("tw"),
                    OrderBy = QueryStringOrZero("ob"),
                    Ascending = QueryStringOrZero("obo") == 0
                };

            if (criteria.EverReferredToId > 0) {
                criteria.EnquiryIds = EnquiryReferralRepository.QueryOver().Where(r => r.ReferredTo.Id == criteria.EverReferredToId).
                        Select(r => r.Enquiry.Id).List<int>().ToList();
            }
            return criteria;   
        }

        private void SetupPaging(int totalRecords)
        {
            if (totalRecords == 0)
            {
                SearchResultMessage.Text = "No Enquiries Found!";
                PagingList.Visible = false;
                ExcelLink.Visible = false;
            }
            else if (totalRecords <= PageSize)
            {
                PagingList.Visible = false;
            }
            else
            {
                var totalPages = (int)Math.Ceiling((double)totalRecords / PageSize);
                var previousPageNumber = CurrentPage - 1;
                if (previousPageNumber < 1)
                    previousPageNumber = 1;
                var nextPageNumber = CurrentPage + 1;
                if (nextPageNumber > totalPages)
                    nextPageNumber = totalPages;

                FirstLink.NavigateUrl = "~/Enquiries/Search.aspx?" + GetQueryString(true);
                PreviousLink.NavigateUrl = "~/Enquiries/Search.aspx?" + GetQueryString(true) + "&page=" + previousPageNumber;
                NextLink.NavigateUrl = "~/Enquiries/Search.aspx?" + GetQueryString(true) + "&page=" + nextPageNumber;
                LastLink.NavigateUrl = "~/Enquiries/Search.aspx?" + GetQueryString(true) + "&page=" + totalPages;

                PagingInfo.Text = "Page " + CurrentPage + " of " + totalPages + " (" + totalRecords + " customers)";
            }
        }

        protected void EnquiriesListItemDataBound(object sender, RepeaterItemEventArgs e)
        {
            if (e.Item.ItemType == ListItemType.Header) {
                var optionsHeader = (HtmlTableCell) e.Item.FindControl("OptionsHeader");
                _optionsHeaderId = optionsHeader.ClientID;

                if (Request.QueryString["view"] != null) {
                    optionsHeader.Visible = false;
                }
            }

            if (e.Item.ItemType != ListItemType.Item && e.Item.ItemType != ListItemType.AlternatingItem) {
                return;
            }

            var enquiry = (Enquiry)e.Item.DataItem;
            var enquiryRow = (HtmlTableRow) e.Item.FindControl("EnquiryRow");
            var ccIdCell = (HtmlTableCell) e.Item.FindControl("CcIdCell");
            var enquiryCell = (HtmlTableCell) e.Item.FindControl("EnquiryCell");
            var sourceCell = (HtmlTableCell) e.Item.FindControl("SourceCell");
            var receivedCell = (HtmlTableCell) e.Item.FindControl("ReceivedCell");
            var deadlineCell = (HtmlTableCell) e.Item.FindControl("DeadlineCell");
            var deptCell = (HtmlTableCell) e.Item.FindControl("DepartmentCell");
            var catCell = (HtmlTableCell) e.Item.FindControl("CategoryCell");
            var statusCell = (HtmlTableCell) e.Item.FindControl("StatusCell");
            var withCell = (HtmlTableCell) e.Item.FindControl("WithCell");            
            var enquiryLink = (HyperLink) e.Item.FindControl("EnquiryLink");
            var enquiryDetail = (Literal) e.Item.FindControl("EnquiryDetail");
            var optionsCell = (HtmlTableCell) e.Item.FindControl("OptionsCell");
            var deleteLink = (HyperLink) e.Item.FindControl("DeleteLink");

            var enquiryLinkText = "Anon:";
            if (enquiry.Customer != null) {
                enquiryLinkText = enquiry.Customer.FullName + ", " + enquiry.Customer.AddressLine + ":";
            }
            enquiryLinkText += enquiry.EnquiryDetail;
            enquiryLinkText = enquiryLinkText.HtmlStripped();           

            if (Request.QueryString["view"] != null) {
                optionsCell.Visible = false;
                ccIdCell.Attributes.Add("style", "vertical-align:top;border: 1px solid #000;");
                enquiryCell.Attributes.Add("style", "vertical-align:top;border: 1px solid #000;");
                enquiryDetail.Text = enquiryLinkText;
                enquiryLink.Visible = false;
                sourceCell.Attributes.Add("style", "vertical-align:top;border: 1px solid #000;");
                receivedCell.Attributes.Add("style", "vertical-align:top;border: 1px solid #000;");
                deadlineCell.Attributes.Add("style", "vertical-align:top;border: 1px solid #000;");
                deptCell.Attributes.Add("style", "vertical-align:top;border: 1px solid #000;");
                catCell.Attributes.Add("style", "vertical-align:top;border: 1px solid #000;");
                statusCell.Attributes.Add("style", "vertical-align:top;border: 1px solid #000;");
                withCell.Attributes.Add("style", "vertical-align:top;border: 1px solid #000;");
                if (enquiry.IsConfidential) {
                    enquiryDetail.Text = "Confidential enquiry. Access only to those involved or admin users!";
                }
            }
            else {
                if (enquiry.Deadline < DateTime.Now && enquiry.Closure == null) {
                    enquiryRow.Attributes.Add("class", "overdue");
                    enquiryRow.Attributes.Add("title", enquiry.Rep != null ? "Made by respresentative - Overdue!" : "Overdue!");
                }
                else {
                    if (enquiry.Rep != null) {
                        enquiryRow.Attributes.Add("title", "Made by respresentative");
                    }
                }

                if (enquiryLinkText.Length > 30) {
                    enquiryLinkText = enquiryLinkText.Substring(0, 29) + "...";
                }
                enquiryLink.Text = enquiryLinkText;
                enquiryLink.NavigateUrl = "~/Enquiries/View.aspx?id=" + enquiry.Id;

                if (enquiry.IsConfidential) {
                    enquiryRow.Attributes.Add("class", "confidential");
                    enquiryRow.Attributes.Add("title", "Confidential enquiry. Access only to those involved or admin users!");
                    enquiryLink.Text = "Confidential";
                }

                optionsCell.Attributes.Add("header", _optionsHeaderId);
                
                if (enquiry.FixYourStreetId == 0) {
                    deleteLink.NavigateUrl = "~/Enquiries/Delete.aspx?id=" + enquiry.Id + "&from=search" + GetQueryString(false);
                }
                else {
                    deleteLink.Visible = false;
                }
                
            }
        }
    }
}